#include"noticement_system.h"
#include"utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/**
 * @brief
 * @param data
 * @param notification
 * @return
 */
ErrorCode addNotification(SystemData* data, Notification* notification) {
    if (data == NULL || notification == NULL) {
        return ERR_INVALID_PARAM;
    }

    notification->next = data->notificationList;
    data->notificationList = notification;

    return OK;
}

/**
 * @brief 获得用户通知，可以指定通知类型
 * @param data 系统数据指针
 * @param userPhone 用户手机号
 * @param type 通知类型(详见NotificationStatus)
 * @param readStatus 通知类型(0-全部，1-未读，2-已读)
 * @param resultList 获得的通知链表
 * @param maxCount 最大读取数量
 * @return
 */
ErrorCode getUserNotifications(SystemData* data, const char* userPhone, NotificationType type,
    int readStatus, Notification** resultList, int maxCount) {
    if (data == NULL || userPhone == NULL || resultList == NULL || maxCount <= 0) {
        return ERR_INVALID_PARAM;
    }
    char logInfoReadStatus[10];

    switch (readStatus)
    {
    case 0:
        strcpy(logInfoReadStatus, "全部");
        break;
    case 1:
        strcpy(logInfoReadStatus, "未读");
        break;
    case 2:
        strcpy(logInfoReadStatus, "已读");
        break;
    default:
        return ERR_INVALID_PARAM;
        break;
    }

    const char* typeStr = getNotificationTypeString(type);

    int count = 0;
    Notification* current = data->notificationList;

    while (current != NULL && count < maxCount) {
        int receiverMatch = (strcmp(userPhone, current->receiverPhone) == 0);

        int typeMatch = ((int)type == 0 || current->notificationType == type);

        int readMatch = (readStatus == 0 ||
            (readStatus == 1 && !current->isRead) ||
            (readStatus == 2 && current->isRead));

        if (receiverMatch && typeMatch && readMatch) {
            resultList[count++] = current;
        }

        current = current->next;
    }

    //记录系统日志
    char logMessage[MAX_DESCRIPTION_LEN];
    sprintf(logMessage, "查询消息记录: 用户=%s, 消息类型=%s, %s, 消息数量=%d",
        userPhone, logInfoReadStatus, typeStr, count);
    logOperation(data, "SYSTEM", logMessage);

    return OK;
}

/**
 * @brief 通过消息ID查询消息内容
 * @param data 系统数据指针
 * @param notificationID 消息ID
 * @return 消息指针
 */
Notification* findNotificationByID(SystemData* data, const char* notificationID) {
    if (data == NULL || notificationID == NULL) {
        return NULL;
    }

    Notification* current = data->notificationList;
    while (current) {
        if (strcmp(current->notificationID, notificationID) == 0) {
            return current;
        }
        current = current->next;
    }

    return NULL;
}

ErrorCode removeNotificationByID(SystemData* data, const char* notificationID) {
    if (data == NULL || notificationID == NULL) {
        return ERR_INVALID_PARAM;
    }

    Notification** ppCurrent = &(data->notificationList);
    while (*ppCurrent) {
        if (strcmp((*ppCurrent)->notificationID, notificationID) == 0) {
            Notification* toRemove = *ppCurrent;
            *ppCurrent = toRemove->next;
            free(toRemove);
            return OK;
        }
        ppCurrent = &((*ppCurrent)->next);
    }

    return ERR_NOT_FOUND;
}

/**
 * @brief 生成唯一的通知ID
 * @param notificationID 存放结果的通知ID指针
 */
void generateNotificationID(char* notificationID) {
    time_t t = time(NULL);
    unsigned int random_part = rand() % 10000;
    sprintf(notificationID, "N%ld%04u", (long int)t, random_part);
}

/**
 * 生成和管理系统内通知
 *
 * @param data 系统数据结构指针
 * @param notificationType 通知类型(对应包裹状态 PackageStatus)
 * @param orderId 相关包裹订单号
 * @param receiver_phone 通知接收者手机号
 *
 * @return 成功返回OK，失败返回错误码
 */
Notification* generateNotification(int notificationType, const char* receiverPhone, const char* packageID) {
    if (receiverPhone == NULL || packageID == NULL) {
        return NULL;
    }

    // 构建通知记录
    Notification* newNotice = (Notification*)malloc(sizeof(Notification));
    if (newNotice == NULL) {
        return NULL;
    }

    generateNotificationID(newNotice->notificationID);

    strcpy(newNotice->receiverPhone, receiverPhone);
    strcpy(newNotice->orderID, packageID);
    newNotice->notificationType = notificationType;
    newNotice->createTime = time(NULL);
    newNotice->isRead = 0;
    newNotice->next = NULL;

    return newNotice;
}

/**
 * @brief 生成并存储通知到系统
 * @param data 系统数据指针
 * @param type 通知类型
 * @param receiverPhone 接收者手机号
 * @param packageID 包裹ID
 * @return 成功返回ID,失败返回错误码
 */
ErrorCode storeNotification(SystemData* data, int type, const char* receiverPhone,
    const char* packageID) {
    if (data == NULL || receiverPhone == NULL || packageID == NULL) {
        return ERR_INVALID_PARAM;
    }


    Notification* notification = generateNotification(type, receiverPhone, packageID);

    if (!notification) {
        return ERR_MEMORY;
    }

    ErrorCode result = addNotification(data, notification);


    if (result != OK) {
        free(notification);
        return result;
    }

    char logMessage[MAX_DESCRIPTION_LEN];
    sprintf(logMessage, "通知已发送: 类型=%d, 包裹=%s, 接收人=%s",
        type, packageID, receiverPhone);
    logOperation(data, "SYSTEM", logMessage);

    return OK;
}

/**
 * 标记通知为已读
 *
 * @param user 用户指针
 * @param notificationID 通知的ID
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode markNotificationAsRead(SystemData* data, const char* notificationID) {
    if (data == NULL || notificationID == NULL) {
        return ERR_INVALID_PARAM;
    }

    Notification* temp = findNotificationByID(data, notificationID);

    if (temp != NULL) {
        temp->isRead = 1;
        return OK;
    }

    return ERR_NOT_FOUND;
}

/**
 * @brief 批量删除过期通知
 * @param data 系统数据指针
 * @param dayThreshold 通知保留期
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode cleanupExpiredNotification(SystemData* data, int dayThreshold) {
    if (data == NULL || dayThreshold <= 0 || dayThreshold > 365) {
        return ERR_INVALID_PARAM;
    }

    time_t currentTime = time(NULL);
    time_t cutoffTime = currentTime - (dayThreshold * 24 * 60 * 60);
    if (cutoffTime < 0) {
        cutoffTime = 0;
    }
    int deletedCount = 0;

    Notification** ppCurrent = &(data->notificationList);
    while (*ppCurrent != NULL) {
        Notification* current = *ppCurrent;

        //检查是否是VIP用户，VIP给与双倍通知保留期
        User* u = findUser(data, current->receiverPhone);
        if (u == NULL) {
            return ERR_INVALID_PARAM;
        }
        UserType t = u->type;
        if (t == USER_VIP) {
            cutoffTime -= (dayThreshold * 24 * 60 * 60);
            if (cutoffTime < 0) {
                cutoffTime = 0;
            }
        }

        if (current->createTime < cutoffTime) {
            *ppCurrent = current->next;
            free(current);
            deletedCount++;
        }
        else {
            ppCurrent = &((*ppCurrent)->next);
        }
    }

    char logMessage[MAX_DESCRIPTION_LEN];
    sprintf(logMessage, "清理过期通知: 删除数量=%d, 阈值=%d天", deletedCount, dayThreshold);
    logOperation(data, "SYSTEM", logMessage);

    return OK;
}
/**
 * @brief 更改包裹状态并发送消息
 * @param data 系统数据指针
 * @param package 包裹指针
 * @param status 包裹状态
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode notifyPackageStatusChange(SystemData* data, Package* package, PackageStatus status) {
    if (data == NULL || package == NULL) {
        return ERR_INVALID_PARAM;
    }

    const char* receiverPhone = NULL;

    switch (status) {
    case STATUS_RECEIVED:
    case STATUS_PICKED:
    case STATUS_EXPIRED:
    case STATUS_DAMAGED:
    case STATUS_LOST:
    case STATUS_RETURNED:
    case STATUS_WRONGPICKED:
        receiverPhone = package->receiverPhone;
        break;
    case STATUS_TRANSPORTING:
        receiverPhone = package->senderPhone;
        break;
    default:
        return ERR_INVALID_STATUS;
    }

    ErrorCode result = storeNotification(data, status, receiverPhone, package->orderId);

    if (result == OK && status == STATUS_WRONGPICKED) {
        result = storeNotification(data, status, package->pickedUpByPhone, package->orderId);
    }

    return result;
}

//包裹到达
ErrorCode notifyPackageArrival(SystemData* data, Package* package) {
    ErrorCode result = notifyPackageStatusChange(data, package, STATUS_RECEIVED);

    if (result == OK) {
        package->notificationStatus = STATUS_NOTIFIED;
        strcpy(package->notifyTime, time(NULL));
    }

    return result;
}
//包裹出库
ErrorCode notifyPackagePickup(SystemData* data, Package* package) {
    return notifyPackageStatusChange(data, package, STATUS_PICKED);
}
//包裹运输
ErrorCode notifyPackageTransporting(SystemData* data, Package* package) {
    return notifyPackageStatusChange(data, package, STATUS_TRANSPORTING);
}
//包裹破损
ErrorCode notifyPackageDamaged(SystemData* data, Package* package) {
    return notifyPackageStatusChange(data, package, STATUS_DAMAGED);
}
//包裹丢失
ErrorCode notifyPackageLost(SystemData* data, Package* package) {
    return notifyPackageStatusChange(data, package, STATUS_LOST);
}
//包裹退回
ErrorCode notifyPackageReturned(SystemData* data, Package* package) {
    return notifyPackageStatusChange(data, package, STATUS_RETURNED);
}
//包裹误领
ErrorCode notifyWrongPickup(SystemData* data, Package* package) {
    return notifyPackageStatusChange(data, package, STATUS_WRONGPICKED);
}


/**
 * @brief 批量生成超期未取提醒通知
 *
 * @param data 系统数据
 * @param daysThreshold 超期天数阈值
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode generatePickupReminders(SystemData* data, int daysThreshold) {
    if (!data || daysThreshold <= 0) {
        return ERR_INVALID_PARAM;
    }

    time_t currentTime = time(NULL);
    int remindersGenerated = 0;

    // 遍历所有包裹
    Package* currentPackage = data->packageList;
    while (currentPackage) {
        // 只处理已通知但未取走的包裹
        if (currentPackage->status == STATUS_RECEIVED &&
            currentPackage->notificationStatus == STATUS_NOTIFIED) {

            // 查找包裹接收者用户
            User* receiver = NULL;
            receiver = findUser(data, currentPackage->receiverPhone);

            // 确定用户的超期阈值
            int userThreshold = daysThreshold;
            if (receiver != NULL && receiver->type == USER_VIP) {
                userThreshold *= 2;  // VIP用户获得更长时间
            }

            // 计算通知后经过的天数
            double diffSeconds = difftime(currentTime, currentPackage->notifyTime);
            int days = (int)(diffSeconds / (60 * 60 * 24));

            // 如果超过阈值，发送提醒
            if (days > userThreshold) {
                ErrorCode result = storeNotification(
                    data, NOTIFICATION_REMINDER,
                    currentPackage->receiverPhone,
                    currentPackage->orderId);

                if (result == OK) {
                    remindersGenerated++;
                }
            }
        }

        currentPackage = currentPackage->next;
    }

    // 记录日志
    char logMessage[MAX_DESCRIPTION_LEN];
    sprintf(logMessage, "批量生成超期未取提醒: 数量=%d, 超期阈值=%d天",
        remindersGenerated, daysThreshold);
    logOperation(data, "SYSTEM", logMessage);

    return OK;
}